package yxy.game.pm2.module.achievement;

import org.redisson.api.RMap;
import yxy.apple.util.StringUtillity;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.achievement;
import yxy.cherry.data.bean.task;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.pm2.bean.db.newDao.AchievementDAO;
import yxy.game.pm2.bean.db.po.AchievementPo;
import yxy.game.pm2.bean.module.BaseGameRedisLockBean;
import yxy.game.pm2.bean.task.Task;

import java.util.*;

public class AchievementModule extends BaseGameRedisLockBean {
    // bean===========================================================================
    private String playerCode;
    private int group;
    private ArrayList<String> taskCodes = new ArrayList<>();

    public String getPlayerCode() {
        return playerCode;
    }

    public void setPlayerCode(String playerCode) {
        this.playerCode = playerCode;
    }

    public int getGroup() {
        return group;
    }

    public void setGroup(int group) {
        this.group = group;
    }

    public ArrayList<String> getTaskCodes() {
        return taskCodes;
    }

    public void setTaskCodes(ArrayList<String> taskCodes) {
        this.taskCodes = taskCodes;
    }

    // func===========================================================================
    // redis==========================================================================
    private static String key(String playerCode) {
        return String.format("PLAYER:%s:MODULE:ACHIEVEMENT", playerCode);
    }

    static private RMap<String, AchievementModule> touchMap(String playerCode) throws RedisException {
        return RedisManager.client(RedisManager.getInstance().getConnection(RedisType.REDIS_GAME)).getMap(key(playerCode));
    }

    public static void init(String playerCode) {
        try {
            if (lockAch(playerCode)) {
                RMap<String, AchievementModule> touch = touchMap(playerCode);
                if (!touch.isExists()) {
                    List<AchievementPo> achievementPos = AchievementDAO.getList(playerCode);

                    if (achievementPos != null && achievementPos.size() > 0) {
                        for (int i = 0; i < achievementPos.size(); i++) {
                            AchievementModule achievementModule = new AchievementModule();
                            achievementModule.setPlayerCode(playerCode);
                            achievementModule.setGroup(achievementPos.get(i).getGroup());

                            //单独处理String转ArrayList
                            String taskCodesStr = achievementPos.get(i).getTaskCodes();
                            achievementModule.setTaskCodes(new ArrayList<String>(Arrays.asList(taskCodesStr.split(","))));

                            touch.put(Integer.toString(achievementPos.get(i).getGroup()), achievementModule);
                        }
                    }
                }

                Map<String, AchievementModule> all = touch.readAllMap();
                Map<String, achievement> datas = DataCenter.getAllData(achievement.class);
                for (achievement data : datas.values()) {
                    if (data.getLevel() == 1 && !all.containsKey(String.valueOf(data.getGroup()))) {
                        create(playerCode, data.getGroup());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            unlockAch(playerCode);
        }
    }

    static public Map<String, AchievementModule> all(String playerCode) {
        try {
            RMap<String, AchievementModule> touch = touchMap(playerCode);
            if (!touch.isExists()) {
                List<AchievementPo> achievementPos = AchievementDAO.getList(playerCode);

                if (achievementPos != null && achievementPos.size() > 0) {
                    for (int i = 0; i < achievementPos.size(); i++) {
                        AchievementModule achievementModule = new AchievementModule();
                        achievementModule.setPlayerCode(playerCode);
                        achievementModule.setGroup(achievementPos.get(i).getGroup());

                        //单独处理String转ArrayList
                        String taskCodesStr = achievementPos.get(i).getTaskCodes();
                        achievementModule.setTaskCodes(new ArrayList<String>(Arrays.asList(taskCodesStr.split(","))));

                        touch.put(Integer.toString(achievementPos.get(i).getGroup()), achievementModule);
                    }
                }
            }

            if (touch.size() == 0) {
                init(playerCode);
            }

            //判断表是否改变，重新更新成就任务
            updateTask(touch, playerCode);

            return touch.readAllMap();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap<>();
    }

    /**
     * 更新成就任务
     *
     * @param touch
     * @param playerCode
     */
    private static void updateTask(RMap<String, AchievementModule> touch, String playerCode) {
        try {
            Map<String, achievement> datas = DataCenter.getAllData(achievement.class);
            ArrayList<Integer> groupList = new ArrayList<>();
            for (achievement value : datas.values()) {
                if (value.getLevel() == 1) {
                    groupList.add(value.getGroup());
                }
            }

            //如果缓存跟表中的不一致，就删除掉
            Map<String, AchievementModule> map = touch.readAllMap();
            for (AchievementModule value : map.values()) {
                //删除
                if (!groupList.contains(value.getGroup())) {
                    for (String taskCode : value.getTaskCodes()) {
                        Task.remove(playerCode, taskCode);
                    }
                    remove(playerCode, String.valueOf(value.getGroup()));
                }
            }


            //如果缓存的比表的group少，就初始该任务group
            for (Integer group : groupList) {
                if(!map.containsKey(String.valueOf(group))){
                    create(playerCode, group);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static public void remove(String playerCode, String groupId) {
        try {
            touchMap(playerCode).remove(groupId);
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }


    static public void set(String playerCode, AchievementModule achievement) {
        try {
            touchMap(playerCode).put(String.valueOf(achievement.getGroup()), achievement);
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }

    static public AchievementModule get(String playerCode, int group) {
        return all(playerCode).get(String.valueOf(group));
    }

    static private void create(String playerCode, int group) throws Exception {
        RMap<String, AchievementModule> touch = touchMap(playerCode);
        Map<String, achievement> datas = DataCenter.getAllData(achievement.class);
        for (achievement data : datas.values()) {
            if (data.getLevel() == 1 && data.getGroup() == group) {
                AchievementModule module = create(playerCode, datas, data);
                touch.put(String.valueOf(module.getGroup()), module);
            }
        }
    }

    static private AchievementModule create(String playerCode, Map<String, achievement> datas, achievement data) {
        AchievementModule module = new AchievementModule();
        module.setPlayerCode(playerCode);
        module.setGroup(data.getGroup());

        achievement temp = data;
        while (temp != null) {
            task taskdata = DataCenter.getData(temp.getTaskid(), task.class);
            Task task = Task.create(playerCode, taskdata);
            module.getTaskCodes().add(task.getCode());
            temp = datas.get(String.valueOf(temp.getFrontid()));
        }

        set(playerCode, module);
        return module;
    }

    //数据归档到数据库
    public static void saveToDB(String playerCode) {
        try {
            //存储
            List<AchievementPo> achievementPos = new ArrayList<>();
            RMap<String, AchievementModule> touch = touchMap(playerCode);
            if (touch.isExists()) {
                for (Map.Entry<String, AchievementModule> entry : touch.readAllEntrySet()) {
                    int key = Integer.parseInt(entry.getKey());
                    AchievementModule value = entry.getValue();
                    AchievementPo achievementPo = new AchievementPo();
                    achievementPo.setPlayerCode(playerCode);
                    achievementPo.setGroup(key);
                    String taskCodes = value.getTaskCodes().toString();
                    if (!StringUtillity.isEmpty(taskCodes)) {
                        taskCodes = taskCodes.replace("[", "");
                        taskCodes = taskCodes.replace("]", "");
                        taskCodes = taskCodes.replace(" ", "");
                    }
                    achievementPo.setTaskCodes(taskCodes);
                    achievementPos.add(achievementPo);

                    AchievementDAO.replace(achievementPos);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //从redis移走数据
    public static void removeAllFromRedis(String playerCode) {
        try {
            touchBucket(key(playerCode)).delete();
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }

    // lock==========================================================================

    static private String lockKey(String playerCode) {
        return String.format("lock:%s", key(playerCode));
    }

    static public boolean lockAch(String playerCode) throws InterruptedException {
        return tryLock(lockKey(playerCode));
    }

    static public void unlockAch(String playerCode) {
        unlock(lockKey(playerCode));
    }

}
